/*
 * Copyright (C) 2008 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.zxing.view;

import com.daxiong.zxing.ResultPoint;
import com.zxing.R;
import com.zxing.camera.CameraManager;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import java.util.ArrayList;
import java.util.List;

/**
 * This view is overlaid on top of the camera preview. It adds the viewfinder
 * rectangle and partial transparency outside it, as well as the laser scanner
 * animation and result points.
 * 
 * @author dswitkin@google.com (Daniel Switkin)
 */
public final class ViewfinderView extends View {

	private static final int[] SCANNER_ALPHA = { 0, 64, 128, 192, 255, 192, 128, 64 };
	private static final long ANIMATION_DELAY = 50L;
	private static final int CURRENT_POINT_OPACITY = 0xA0;
	private static final int MAX_RESULT_POINTS = 20;
	private static final int POINT_SIZE = 6;

	private CameraManager cameraManager;
	private final Paint paint;
	private final Paint paint2;
	private Bitmap resultBitmap;
	private final int maskColor;
	private final int resultColor;
	private final int laserColor;
	private int scannerAlpha;
	private List<ResultPoint> possibleResultPoints;

	// This constructor is used when the class is built from an XML resource.
	public ViewfinderView(Context context, AttributeSet attrs) {
		super(context, attrs);

		// Initialize these once for performance rather than calling them every
		// time in onDraw().
		paint = new Paint(Paint.ANTI_ALIAS_FLAG);
		paint2 = new Paint(Paint.ANTI_ALIAS_FLAG);
		Resources resources = getResources();
		maskColor = resources.getColor(R.color.viewfinder_mask);
		resultColor = resources.getColor(R.color.result_view);
		laserColor = resources.getColor(R.color.status_text);

		scannerAlpha = 0;
		possibleResultPoints = new ArrayList<>(5);
	}

	public void setCameraManager(CameraManager cameraManager) {
		this.cameraManager = cameraManager;

	}

	@SuppressLint("DrawAllocation")
	@Override
	public void onDraw(Canvas canvas) {
		if (cameraManager == null) {
			return; // not ready yet, early draw before done configuring
		}

		// 添加的代码
		int statusbar = cameraManager.getStatusBarHeight(getContext());
		int actionbar = cameraManager.getActionBarHeight(getContext());
		int discount = statusbar + actionbar;
		int min = (statusbar + actionbar) / 2;

		Rect frame = cameraManager.getFramingRect(discount);// 返回长和宽分辨率相同的矩形框
		Rect previewFrame = cameraManager.getFramingRectInPreview();
		if (frame == null || previewFrame == null) {
			return;
		}
		int width = canvas.getWidth();
		int height = canvas.getHeight();// 当设置没有覆盖整个屏幕的时候，这里返回的是当前surfaceview的高度，而getFramingRect计算的时候是用了整块屏幕的高度和宽度

		// 绘制的矩形对焦区域，这个区域实际上的大小是frame的返回值，为了对焦更快可以缩小对焦区域
		paint.setColor(resultBitmap != null ? resultColor : maskColor);
		Rect fadeframe = new Rect();
		fadeframe.left = frame.left + min;
		fadeframe.right = frame.right - min;
		fadeframe.top = frame.top + min;
		fadeframe.bottom = frame.bottom - min;
		canvas.drawRect(0, 0, width, fadeframe.top, paint);// 上
		canvas.drawRect(0, fadeframe.top, fadeframe.left, fadeframe.bottom, paint);// 左
		canvas.drawRect(fadeframe.right, fadeframe.top, width, fadeframe.bottom, paint);// 右
		canvas.drawRect(0, fadeframe.bottom, width, height, paint);// 下

		
		// 绘制4个边角
		paint2.setColor(laserColor);
		canvas.drawRect(fadeframe.left, fadeframe.top, fadeframe.left + statusbar, fadeframe.top + 3, paint2);
		canvas.drawRect(fadeframe.left, fadeframe.top, fadeframe.left + 3, fadeframe.top + statusbar, paint2);
		canvas.drawRect(fadeframe.right - statusbar, fadeframe.top, fadeframe.right, fadeframe.top + 3, paint2);
		canvas.drawRect(fadeframe.right - 3, fadeframe.top, fadeframe.right, fadeframe.top + statusbar, paint2);
		canvas.drawRect(fadeframe.left, fadeframe.bottom - 3, fadeframe.left + statusbar, fadeframe.bottom, paint2);
		canvas.drawRect(fadeframe.left, fadeframe.bottom - statusbar, fadeframe.left + 3, fadeframe.bottom, paint2);
		canvas.drawRect(fadeframe.right - statusbar, fadeframe.bottom - 3, fadeframe.right, fadeframe.bottom, paint2);
		canvas.drawRect(fadeframe.right - 3, fadeframe.bottom - statusbar, fadeframe.right, fadeframe.bottom, paint2);

		if (resultBitmap != null) {
			// Draw the opaque result bitmap over the scanning rectangle
			paint.setAlpha(CURRENT_POINT_OPACITY);
			canvas.drawBitmap(resultBitmap, null, frame, paint);
		} else {

			// 中间的扫描线
			paint.setColor(laserColor);
			paint.setAlpha(SCANNER_ALPHA[scannerAlpha]);
			scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length;
			int middle = frame.height() / 2 + frame.top;
			canvas.drawRect(fadeframe.left, middle - 1, fadeframe.right, middle + 2, paint);

			// Request another update at the animation interval, but only
			// repaint the laser line, not the entire viewfinder mask.
			//特定区域刷新
			postInvalidateDelayed(ANIMATION_DELAY, frame.left - POINT_SIZE, frame.top - POINT_SIZE, frame.right
					+ POINT_SIZE, frame.bottom + POINT_SIZE);
		}
	}

	public void drawViewfinder() {
		Bitmap resultBitmap = this.resultBitmap;
		this.resultBitmap = null;
		if (resultBitmap != null) {
			resultBitmap.recycle();
		}
		invalidate();
	}

	/**
	 * Draw a bitmap with the result points highlighted instead of the live
	 * scanning display.
	 * 
	 * @param barcode
	 *            An image of the decoded barcode.
	 */
	public void drawResultBitmap(Bitmap barcode) {
		resultBitmap = barcode;
		invalidate();
	}

	public void addPossibleResultPoint(ResultPoint point) {
		List<ResultPoint> points = possibleResultPoints;
		synchronized (points) {
			points.add(point);
			int size = points.size();
			if (size > MAX_RESULT_POINTS) {
				// trim it
				points.subList(0, size - MAX_RESULT_POINTS / 2).clear();
			}
		}
	}

}
